/**
 * Render Bender - A Flash-based chained Pixel Bender kernel previewer
 * Copyright (C) 2009  David Lenaerts
 * 
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 * 
 * Author information:
 * David Lenaerts
 * url: http://www.derschmale.com
 * mail: david.lenaerts@gmail.com
 * 
 */
 
package com.derschmale.renderBender.model
{
	import com.derschmale.renderBender.ApplicationFacade;
	import com.derschmale.renderBender.model.vo.AssetDefinition;
	import com.derschmale.renderBender.model.vo.ChainDefinitionVO;
	import com.derschmale.renderBender.model.vo.KernelDefinition;
	import com.derschmale.renderBender.model.vo.KernelImageDefinition;
	
	import flash.events.Event;
	import flash.net.URLLoader;
	import flash.net.URLRequest;
	
	import org.puremvc.as3.patterns.proxy.Proxy;
	
	/**
	 * The use of ChainXMLParser and the Definition value objects may look like overkill, but this is chiefly not to run into problems when I decide
	 * not to use XML for chain definition.
	 * Also, the definition files make it easier to store per-kernel/image data needed for the KernelSequence class.
	 */
	public class ChainXMLProxy extends Proxy
	{
		public static const NAME : String = "ChainXMLProxy";
		
		private var _xml : XML;
		
		public function ChainXMLProxy()
		{
			super(NAME, new ChainDefinitionVO());
		}
		
		public function setXML(xml : XML) : void
		{
			_xml = xml;
			parse();
			sendNotification(ApplicationFacade.CREATE_SEQUENCE, chainDefinition);
		}
		
		public function get chainDefinition() : ChainDefinitionVO
		{
			return data as ChainDefinitionVO;
		}
		
		public function get assetDefinitions() : Vector.<AssetDefinition>
		{
			return data.assetDefinitions;
		}
		
		public function get kernelDefinitions() : Vector.<KernelDefinition>
		{
			return data.kernelDefinitions;
		}
		
		public function load(url : String) : void
		{
			var loader : URLLoader = new URLLoader();
			var urlRequest : URLRequest = new URLRequest(url);
			loader.addEventListener(Event.COMPLETE, onLoadComplete, false, 0, true);
			loader.load(urlRequest);
		}
		
		private function onLoadComplete(event : Event) : void
		{
			var loader : URLLoader = URLLoader(event.target);
			_xml = new XML(loader.data);
			parse();
			sendNotification(ApplicationFacade.CREATE_SEQUENCE, chainDefinition);
		}
		
		private function parse() : void
		{
			parseAssets();
			parseSequence();
		}
		
		/* TO DO: add validation */
		private function parseAssets() : void
		{
			var definition : AssetDefinition;
			var assetNode : XML;
			
			chainDefinition.assetDefinitions = new Vector.<AssetDefinition>();
			
			for (var i : int = 0; i < _xml.assets.asset.length(); i++) {
				assetNode = _xml.assets.asset[i];
				definition = new AssetDefinition();
				definition.type = assetNode.@type;
				definition.id = assetNode.@id;
				if (definition.type == "BitmapData") {
					definition.channels = assetNode.@alpha == "true"? 4 : 3;
					definition.src = assetNode.@src;
				}
				else {
					definition.channels = assetNode.@channels;
				}
				definition.width = assetNode.@width;
				definition.height = assetNode.@height;
				chainDefinition.assetDefinitions.push(definition);
			}
		}
		
		private function parseSequence() : void
		{
			chainDefinition.kernelDefinitions = new Vector.<KernelDefinition>();
			for (var i : int = 0; i < _xml.sequence.kernel.length(); i++) {
				parseKernel(_xml.sequence.kernel[i]);
			}
		}
		
		/* TO DO: add validation */
		private function parseKernel(kernelNode : XML) : void
		{
			var imgNode : XML;
			var kernelDef : KernelDefinition = new KernelDefinition();
			var imageDef : KernelImageDefinition = new KernelImageDefinition();

			kernelDef.src = kernelNode.@src;
			
			if (kernelNode.@method && kernelNode.@method != "")
				kernelDef.method = kernelNode.@method
			else
				kernelDef.method = KernelDefinition.SHADER_JOB_METHOD;
			
			for (var i : int = 0; i < kernelNode.input.length(); i++) {
				imgNode = kernelNode.input[i];
				imageDef = new KernelImageDefinition();
				imageDef.assetId = imgNode.@assetId;
				imageDef.name = imgNode.@name;
				kernelDef.inputs.push(imageDef);
			}
			
			kernelDef.output = new KernelImageDefinition();
			kernelDef.output.assetId = kernelNode.output.@assetId;
			kernelDef.output.name = kernelNode.input.@name;
			chainDefinition.kernelDefinitions.push(kernelDef);
		}
	}
}